/// @tags: DS SET DivideBlock
#include <cstdio>
#include <iostream>

using std::cin;
using std::cout;
using std::make_pair;
using std::max;
using std::min;

namespace BlueQuantum {

typedef long long LL;

constexpr int MAXN = 1e5 + 3, BLK = 3e2;

int n, m, top, num;
int fire[MAXN], fcnt[MAXN], L[MAXN], R[MAXN], bel[MAXN];
LL a[MAXN], sum[MAXN], add[MAXN];
std::pair<int, int> stk[MAXN], tmp[MAXN];

void modify(int l, int r, LL v) {
  if (bel[l] == bel[r]) {
    for (int i = l; i <= r; ++i) a[i] += v * fire[i], sum[bel[i]] += v * fire[i];
    return;
  }
  for (int i = bel[l] + 1; i <= bel[r] - 1; ++i) sum[i] += v * fcnt[i], add[i] += v;
  for (int i = l; i <= R[bel[l]]; ++i) a[i] += v * fire[i], sum[bel[i]] += v * fire[i];
  for (int i = L[bel[r]]; i <= r; ++i) a[i] += v * fire[i], sum[bel[i]] += v * fire[i];
}

LL query(int l, int r) {
  LL v = 0;
  if (bel[l] == bel[r]) {
    for (int i = l; i <= r; ++i) v += a[i] + add[bel[i]] * fire[i];
    return v;
  }
  for (int i = bel[l] + 1; i <= bel[r] - 1; ++i) v += sum[i];
  for (int i = l; i <= R[bel[l]]; ++i) v += a[i] + add[bel[i]] * fire[i];
  for (int i = L[bel[r]]; i <= r; ++i) v += a[i] + add[bel[i]] * fire[i];
  return v;
}

inline void update(int x, bool status) {
  if (fire[x] == status) return;
  if (status)
    a[x] = -add[bel[x]], fcnt[bel[x]]++;
  else
    sum[bel[x]] -= a[x] + add[bel[x]], a[x] = 0, fcnt[bel[x]]--;
  fire[x] = status;
}

inline void update(int l, int r, int status) {
  for (int i = l; i <= r; ++i) update(i, status);
}

inline int main() {
  cin >> n >> m;
  for (int i = 1; i <= n; ++i)
    cin >> a[i], sum[bel[i] = (i - 1) / BLK + 1] += a[i], fcnt[bel[i]] += fire[i] = true;
  for (int i = 1; i <= bel[n]; ++i) L[i] = BLK * (i - 1) + 1, R[i] = BLK * i;
  R[bel[n]] = n;
  while (m--) {
    int opt, l, r, k;
    bool flag = false;
    cin >> opt;
    if (opt == 1) cin >> l >> r >> k, modify(l, r, k);
    if (opt == 2) cin >> l >> r, cout << query(l, r) << '\n';
    if (opt == 3) {
      cin >> k;
      for (int i = 1; i <= top; ++i) {
        if (k >= stk[i].first && k <= stk[i].second) {
          flag = true;
          break;
        }
      }
      if (!flag) {
        top++;
        for (int i = top; i; --i) {
          if (k > stk[i - 1].second && (k < stk[i + 1].first || i == top)) {
            stk[i] = make_pair(k, k), update(k, 0);
            break;
          }
          stk[i] = stk[i - 1];
        }
      }
    }
    if (opt == 4) {
      cin >> l >> r, num = 0;
      for (int i = 1; i <= top; ++i) {
        if (l <= stk[i].first && r >= stk[i].second)
          update(stk[i].first, stk[i].second, true);
        else if (l > stk[i].second || r < stk[i].first)
          tmp[++num] = stk[i];
        else {
          if (l > stk[i].first)
            update(l, min(stk[i].second, r), true), tmp[++num] = make_pair(stk[i].first, l - 1);
          if (r < stk[i].second)
            update(max(stk[i].first, l), r, true), tmp[++num] = make_pair(r + 1, stk[i].second);
        }
      }
      top = 0;
      for (int i = 1; i <= num; ++i) stk[++top] = tmp[i];
    }
    if (!top) continue;
    for (int i = 1; i <= top; ++i) {
      update(stk[i].first = max(stk[i].first - 1, 1), false);
      update(stk[i].second = min(stk[i].second + 1, n), false);
    }
    num = 1;
    for (int i = 2; i <= top; ++i) {
      if (stk[i].first <= stk[num].second + 1)
        stk[num].second = stk[i].second;
      else
        stk[++num] = stk[i];
    }
    top = num;
  }
  return 0;
}

}  // namespace BlueQuantum

int main() {
#ifndef ONLINE_JUDGE
#ifdef LOCAL
  freopen("/tmp/CodeTmp/testdata.in", "r", stdin);
  freopen("/tmp/CodeTmp/testdata.out", "w", stdout);
#else
  freopen("tree.in", "r", stdin);
  freopen("tree.out", "w", stdout);
#endif
#endif

  std::ios::sync_with_stdio(false), cin.tie(NULL), cout.tie(NULL);
  return BlueQuantum::main();
}
